#!/bin/sh
#
# Send a text message to the LCD screen of a QNAP device
#
# Example crontab entry (send hostname and RAID status every minute):
#
#   * * * * * qnap_lcd_message "$(hostname)" "RAID: $(grep --only-matching '\[[U_]\+\]' /proc/mdstat)"
#
# License: GPLv3 or later
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Copyright 2021 Lars Kruse <devel@sumpfralle.de>
# Copyright 2016 Justin Duplessis <drfoliberg@gmail.com>
# Copyright Dirk Brenken (dibdot@gmail.com)
#


set -eu

# hexadecimal codes are not interpreted by the shell-builtin for printf
PRINTF=/usr/bin/printf

LCD_DEV=${LCD_DEV:-/dev/ttyS1}
LCD_BAUD=${LCD_BAUD:-1200}
LCD_MAXROW=${LCD_MAXROW:-2}
LCD_MAXCOL=${LCD_MAXCOL:-16}
LCD_ON="M\x5E\x01"
# shellcheck disable=SC2034
LCD_OFF="M\x5E\x00"
LCD_CODE="M\x0C\x"
LCD_CLEAR="M\x0D"
LCD_RESET="M\xFF"
TTY_TIMEOUT=10
TTY_MIN=0


send_to_lcd() {
    cat >"$LCD_DEV"
}


init_lcd() {
    stty -F "$LCD_DEV" "$LCD_BAUD" cread cbreak olcuc time "$TTY_TIMEOUT" min "$TTY_MIN"
    "$PRINTF" "$LCD_RESET" | send_to_lcd
    "$PRINTF" "$LCD_ON" | send_to_lcd
    "$PRINTF" "$LCD_CLEAR" | send_to_lcd
}


write_line() {
    local row="$1"
    local text="$2"
    local row_code
    text=$(printf '%s' "$text" | sed 's/\\%/\\\\%/g')
    row_code=$(printf '%s%02x' "$LCD_CODE" "$row")
    "$PRINTF" "$row_code %-${LCD_MAXCOL}s" "$text" | send_to_lcd
    "$PRINTF" "$row_code %-${LCD_MAXCOL}s" "$text" | send_to_lcd
}

init_lcd
row=0
for text in "$@"; do
    write_line "$row" "$text"
    row=$((row + 1))
    if [ "$((row + 1))" -gt "$LCD_MAXROW" ]; then break; fi
done
